#include "usart0_driver.h"
#include "gd32f4xx.h"
#include "systick.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>

void usart0_driver_tx_config(void)
{

    // U0T:usart0_tx 对应PA9引脚
    // 串口外设时钟使能
    rcu_periph_clock_enable(RCU_USART0);
    // 引脚外设时钟使能
    rcu_periph_clock_enable(RCU_GPIOA);

    // 输出复用
    //  引脚复用功能配置
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_9);
    // af7对应usart0_tx
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_9);
    //gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9);

    // 串口配置
    // 复位
    usart_deinit(USART0);
    // 比特率
    usart_baudrate_set(USART0, 115200);
    // 校验位
    usart_parity_config(USART0, USART_PM_NONE);
    // 字宽:8
    usart_word_length_set(USART0, USART_WL_8BIT);
    // 停止位:1bit
    usart_stop_bit_set(USART0, USART_STB_1BIT);
    // 先发送低位,后发送高位
    usart_data_first_config(USART0, USART_MSBF_LSB);

    // 打开发送功能
    usart_transmit_config(USART0, USART_TRANSMIT_ENABLE);
    // 打开串口总开关
    usart_enable(USART0);
}

/**
 * 串口接收
 */
void usart0_driver_rx_config(void)
{
    // 串口接收:使用PA10引脚
    // 设置复用输出模式
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_10);
    // 使用引脚pa10的复用功能usart0_rx的串口接收
    gpio_af_set(GPIOA, GPIO_AF_7, GPIO_PIN_10);

    // 配置串口接收
    usart_receive_config(USART0, USART_RECEIVE_ENABLE);
    // 开启中断
    nvic_irq_enable(USART0_IRQn, 2, 2);
    // 开启rbne中断接收
    usart_interrupt_enable(USART0, USART_INT_RBNE);
    // 开启idle中断接收
    usart_interrupt_enable(USART0, USART_INT_IDLE);
    // 开启usart0总开关
    usart_enable(USART0);
}

static uint8_t rx_data[1024] = {0};
static uint16_t rx_index = 0;
void clear_receive_data(void)
{
    rx_index = 0;
    memset(rx_data, 0, sizeof(rx_data));
}

extern void onReceiveData(uint8_t *data, uint16_t len);
//extern void onUsart0_Interrupt(void);

// 实现usart0的中断函数
void USART0_IRQHandler(void)
{
    // 监听brne与idle两个中断
    if (SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_RBNE))
    {
        // 清除标记
        usart_interrupt_flag_clear(USART0, USART_INT_FLAG_RBNE);
        // 读取数据
        rx_data[rx_index] = (uint8_t)usart_data_receive(USART0);
        rx_index++;
    }

    // 监听idle中断

    if (SET == usart_interrupt_flag_get(USART0, USART_INT_FLAG_IDLE))
    {
        // 清除标记,与其他不同,需要通过读取,清除标记
        usart_data_receive(USART0);
        rx_data[rx_index] = '\0';

        onReceiveData(rx_data, rx_index);
        

        clear_receive_data();
    }

    //onUsart0_Interrupt();
}

void send_byte(uint8_t data)
{
    usart_data_transmit(USART0, data);
    while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
        ;
}

 int fputc(int ch, FILE *f)
{
     send_byte((uint8_t)ch);
     return ch;
 }

void usart0_driver_tx_test()
{
    static uint8_t i = 0;
    // 发送'
    i++;
    // 将被发送数据放入缓冲区,
    send_byte(i);

    // 如果缓冲区清空,代表串口已经把数据发出去了
    // USART_FLAG_TBE:1表示缓冲区清空,0,代表未清空
    // 芯片会自动置0置1
    // 下边代码返回1,代表发送成功,
    // 返回1,表示发送完成,否则,
    // 等待数据发送完成
    // USART_FLAG_TBE是串口通信中用于指示发送缓冲区空（Transmit Buffer Empty）的状态标志
    while (RESET == usart_flag_get(USART0, USART_FLAG_TBE))
        ;

    delay_1ms(1000);
}

void usart0_driver_rx_test(void)
{
}
